package com.minis.context;

import com.minis.beans.BeanDefinition;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.net.URL;
import java.util.*;

/**
 * @Author:刘瑞
 * @Date:2024/8/11 16:07
 * @Description: 解析 xml文件,利用Java的反射机制创建对象平且将创建的对象 添加到对用map中
 **/
public class ClassPathXmlApplicationContext {
    // 用于存储从Xml中解析的信息 id 和classPath
    private List<BeanDefinition> beanDefinitions = new ArrayList<>();
    // 用于存储创建的对象的实例和名称
    private Map<String, Object> singletons = new HashMap<>();
    //构造器获取外部配置，解析出Bean的定义，形成内存映像
    public ClassPathXmlApplicationContext(String fileName) {
        this.readXml(fileName);
        this.instanceBeans();
    }

    // 通过传入的文件路径，也就是 XML 文件的全路径名，来获取 XML 内的信息
    private void readXml(String fileName) {
        SAXReader saxReader = new SAXReader();
        // 获取文件的目录
        URL xmlPath = this.getClass().getClassLoader().getResource(fileName);

        try {
            Document document = saxReader.read(xmlPath);
            Element rootElement = document.getRootElement();
            List<Element> elements = (List<Element>) rootElement.elements();
            Iterator<Element> iterator = elements.iterator();
            while (iterator.hasNext()) {
                Element item = iterator.next();
                // 获取bean的基本信息

                String id = item.attributeValue("id");
                String beanClassName = item.attributeValue("class");

                BeanDefinition beanDefinition = new BeanDefinition(id, beanClassName);

                System.out.println(fileName + "item信息为：" + beanDefinition.toString());
                //将Bean的定义存放到beanDefinitions
                beanDefinitions.add(beanDefinition);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //利用反射创建Bean实例，并存储在singletons中
    private void instanceBeans() {
        try {
            for (BeanDefinition beanDefinition : beanDefinitions) {
                singletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //这是对外的一个方法，让外部程序从容器中获取Bean实例，会逐步演化成核心方法
    public Object getBean(String beanName) {
        return singletons.get(beanName);
    }
}
